package com.dzsw.camunda.exception;

import cn.dev33.satoken.exception.NotLoginException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.*;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class GlobalExceptionFilter implements Filter {

    private ObjectMapper objectMapper;

    private Object lock = new Object();

    private ServletContext servletContext;

    public GlobalExceptionFilter() {

    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.debug("GlobalExceptionFilter -> init");
        this.servletContext = filterConfig.getServletContext();
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        ObjectMapper objectMapperToUse = this.objectMapper;
        if (objectMapperToUse == null) {
            synchronized (this.lock) {
                objectMapperToUse = this.objectMapper;
                if (objectMapperToUse == null) {
                    WebApplicationContext wac = WebApplicationContextUtils.findWebApplicationContext(servletContext);
                    if (wac == null) {
                        throw new IllegalStateException("No WebApplicationContext found: " +
                                "no ContextLoaderListener or DispatcherServlet registered?");
                    }
                    objectMapperToUse = wac.getBean(ObjectMapper.class);
                }
                this.objectMapper = objectMapperToUse;
            }
        }

        invokeFilter(request, response, chain);
    }

    private void invokeFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        try {
            chain.doFilter(request, response);
        } catch (Throwable e) {
            response.setContentType("application/json;charset=UTF-8");
            objectMapper.writeValue(response.getOutputStream(), handleException(e));
        }
    }

    @Override
    public void destroy() {
        log.debug("MyShiroFilter -> destroy");
    }

    /**
     * 处理异常返回消息
     *
     * @param e
     * @return
     */
    public Map<String, String> handleException(Throwable e) {
        Map<String, String> mapData = new HashMap<>();
        if (NotLoginException.class.isInstance(e.getCause())) {
            NotLoginException exception = (NotLoginException) e.getCause();
            mapData.put("loginType", exception.getLoginType());
            mapData.put("msg", exception.getMessage());
        } else {
            mapData.put("loginType", e.getMessage());
            mapData.put("msg", e.getCause().toString());
        }
        return mapData;
    }
}
